# -*- coding: utf-8 -*-
# @Time    : 2016/9/9

from sympy import Function, diff, sympify, Eq, solve
from mathsolver.functions.base import BaseFunction, BaseFunc, BaseEq, new_latex, BaseFuncName, BaseNumber
from mathsolver.functions.daoshu.daoshuyunsuan import HanShuDaoShuYunSuan
from mathsolver.functions.budengshi.common_opers import find_reg_expr


class HanShuDaoShuQiuZhi(BaseFunction):
    """函数的导数求值"""

    def solver(self, *args):

        # 输入为 BaseEq（在 x=2 处） 或者 BaseFuncName（求 f'(2)）
        if isinstance(args[0], BaseEq):
            x_var = args[0].value[1]
            func = BaseFuncName({"name": "f", "type": "deri", "var": x_var})
        else:
            func = args[0]

        if len(args) > 1:
            known_func = args[1]
        else:
            known_func = self.search(func.name)
        expr = known_func.expression
        var = known_func.var
        diff_expr = diff(expr, var)

        self.steps.append(["对函数求导得 {}'({}) = {}".format(new_latex(known_func.name), new_latex(var), new_latex(diff_expr)), ""])

        if not func.var.is_Symbol:
            expr = diff_expr.subs({known_func.var: func.var})
            self.steps.append(["所以 %s = " % func.printing(), new_latex(expr)])
            self.output.append(BaseNumber(expr))
            self.label.add("函数的导数求值")
        else:
            self.output.append(BaseNumber(diff_expr))
        return self


class HanShuDaoShuQiuZhiFD(BaseFunction):
    """解析式含导数值的求导运算, 求 f'(a)的值
    """

    def solver(self, *args):
        funceq = args[0]
        func = funceq.eq2func()
        funcname_d = args[1]

        # 将导数值看为常数，对等号两边求导
        deriv = HanShuDaoShuYunSuan().solver(func).output[0]

        self.steps.append(["因为 {}".format(func.printing().replace("f_{d}", "f'").replace("\\operatorname", "")),
                           "所以 {}".format(deriv.printing().replace("f_{d}", "f'").replace("\\operatorname", ""))])

        # 从f'(a)中提取出 a, a 可能是表达式，比如 pi/3
        constant = funcname_d.var
        # 将 a 代入等式，并求出 f'(a) 的值
        expression_subs = deriv.expression.subs(func.var, constant)
        self.steps.append(["令{0} = {1}".format(deriv.var, constant),
                           "则 f'({0}) = {1}".format(constant, new_latex(expression_subs).replace("f_{d}", "f'").replace(
                               "\\operatorname", ""))])

        # 将 f'(a) 的值代入求导后的等式，得到 f'(x) 的表达式
        f_d = Function("f_d")
        val = solve(Eq(f_d(constant), expression_subs))[0][f_d(constant)]
        deriv_subs = deriv.expression.subs(f_d(constant), val).simplify()

        self.steps.append(["即 {0}({1}) = {2}".format(deriv.name, constant, val),
                           # "则 {0}({2}) = {2}".format(deriv.name, new_latex(deriv.var), new_latex(deriv_subs))
                           ""])

        self.output.append(BaseFunc({"var": "x", "name": "f_d", "type": "", "expression": deriv_subs}))

        self.label.add("解析式含导数值的求导运算")

        return self


class HanShuDaoShuQiuZhiF(BaseFunction):
    """
    解析式含导数值的求导运算, 求 f(a)的值
    """
    def solver(self, *args):
        funceq = args[0]
        func = funceq.eq2func()
        # 将导数值看为常数，对等号两边求导
        deriv = HanShuDaoShuYunSuan().solver(func).output[0]
        self.steps.append(["因为 {}".format(func.printing().replace("f_{d}", "f'").replace("\\operatorname", "")),
                           "所以 {}".format(deriv.printing().replace("f_{d}", "f'").replace("\\operatorname", ""))])

        # 从f'(a)中提取出 a, a 可能是表达式，比如 pi/3
        # constant = funcname.var  # 问题可能是求 f(x) 从 funceq 中提取出 a
        funceq_right = sympify(funceq.value[1])
        f_d_pattern = find_reg_expr(r"f_d\(.*?\)", str(funceq_right))[0]
        constant = sympify(f_d_pattern).args[0]

        # 将 a 代入等式，并求出 f'(a) 的值
        expression_subs = deriv.expression.subs(func.var, constant)
        self.steps.append(["令{0} = {1}".format(deriv.var, constant),
                           "则 f'({0}) = {1}".format(constant, new_latex(expression_subs).replace("f_{d}", "f'").replace(
                               "\\operatorname", ""))])

        # 将 f'(a) 的值代入问题中的等式，得到 f(x) 的表达式
        f_d = Function("f_d")
        val = solve(Eq(f_d(constant), expression_subs))[0][f_d(constant)]
        _, right = func.sympify()
        original_expr_subs = right.subs(f_d(constant), val).simplify()
        self.steps.append(["则 {0}({1}) = {2}".format(deriv.name, constant, val),
                           # "则 {0}({2}) = {2}".format(func.name, func.var, new_latex(original_expr_subs))
                           ""])
        self.output.append(BaseFunc({"var": "x", "name": "f_d", "type": "", "expression": original_expr_subs}))
        self.label.add("解析式含导数值的求导运算")
        return self


if __name__ == '__main__':
    pass
